<?php

namespace App\Http\Model;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class DailyStatisticsModel extends Base
{
    protected $statCon = 'statistics';

    protected $table = "union";
    protected $userTable = "user";
    protected $userLoginLogTable = 'user_login_log';
    protected $userRegisterTable = 'user_register_log';
    protected $roomOpenTimeTable = 'room_open_time';
    protected $roomMicroLogTable = 'room_micro_log';
    protected $rechargeOrderTable = 'finance_recharge_order';
    protected $diamondStreamTable = 'finance_diamond_stream';
    protected $roomJoinTable = 'room_join_log';
    protected $unionRoomTable = 'union_room';

    //statistics库
    protected $statDailyTable = 'stat_daily';
    protected $statDailyRoomTable = 'stat_daily_room';


    private $userActiveSet = 'USER:ACTIVE:';//用户活跃 USER:ACTIVE:{Ymd}=>{user_id}

    public function __construct(array $attributes = [])
    {
        parent::__construct($this->table, $attributes);
    }


    //统计数据 每日数据
    public function statisticalData($timeStr, $timeEnd)
    {
        $dateStr = date("Y-m-d H:i:s", $timeStr);
        $dateEnd = date("Y-m-d H:i:s", $timeEnd);

        //新增用户（新增激活）
        //新安装第一次启动应用的用户以设备为判断标准）
        $userNewNum = DB::table($this->userTable)
            ->where('create_time', '>=', $dateStr)
            ->where('create_time', '<=', $dateEnd)
            ->count();

        // 活跃用户（总）
        // 每日启动过应用的用户（去重），启动过一次的用户即视为活跃用户，包括新用户与老用户
        $key = $this->userActiveSet . date("Ymd", $timeStr);
        $userIds = Redis::SMEMBERS($key);
        $activeNumAll = count($userIds);

        // 活跃用户（安卓）
        // 每日启动过应用的用户（去重），启动过一次的用户即视为活跃用户，包括新用户与老用户
        // 活跃用户（ios）
        // 每日启动过应用的用户（去重），启动过一次的用户即视为活跃用户，包括新用户与老用户
        $activeNumAndroid = 0;
        $activeNumIos = 0;
        if (!empty($userIds)) {
            $loginLog = DB::table($this->userLoginLogTable)
                ->select('user_id', DB::raw('MIN(id) as id'))
                ->whereIn('user_id', $userIds)
                ->groupBy('user_id')
                ->get();
            $loginLog = self::objToArray($loginLog);
            if (!empty($loginLog)) {
                $ids = array_column($loginLog, 'id');
                $activeNumAndroid = DB::table($this->userLoginLogTable)
                    ->whereIn('id', $ids)
                    ->where('os_name', 'Android')
                    ->count();
            }
            $activeNumIos = $activeNumAll - $activeNumAndroid;
        }
        // 开播厅数
        // 每日开播的厅数（去重）
        $roomOpenNumAll = DB::table($this->roomOpenTimeTable)
            ->where('date', $timeStr)
            ->count();

        // 有效开播房间数
        //     每日开播≥5分钟的房间总数
        $roomOpenNumTrue = DB::table($this->roomOpenTimeTable)
            ->where('date', $timeStr)
            ->where('total_time', '>=', 300)
            ->count();

        // 上麦用户人数（含主播）
        //     每日进入进入直播间成功上麦的总人数（去重）
        $microLog = DB::table($this->roomMicroLogTable)
            ->where('created_at', '>=', $dateStr)
            ->where('created_at', '<=', $dateEnd)
            ->select('user_id', 'room_id', 'micro_id', 'type', 'created_at')
            ->get();
        $microLog = self::objToArray($microLog);
        $userIds = [];
        $userRoomMap = [];
        foreach ($microLog as $val) {
            $userIds[$val['user_id']] = 1;
            $key = $val['user_id'] . '|' . $val['room_id'];
            $userRoomMap[$key]['total'] = empty($userRoomMap[$key]['total']) ? 0 : $userRoomMap[$key]['total'];
            if ($val['type'] == 1) {//上麦
                //有上麦没有下麦记录就记1分钟
                if (!empty($userRoomMap[$key]['created_at'])) {
                    $userRoomMap[$key]['total'] = $userRoomMap[$key]['total'] + 60;
                }
                $userRoomMap[$key]['nowType'] = 1;
                $userRoomMap[$key]['created_at'] = $val['created_at'];
            } else {//下麦
                //没有上麦记录就记1分钟
                if (empty($userRoomMap[$key]['created_at'])) {
                    $userRoomMap[$key]['total'] = $userRoomMap[$key]['total'] + 60;
                } else {
                    $userRoomMap[$key]['total'] = $userRoomMap[$key]['total'] + (strtotime($val['created_at']) - strtotime($userRoomMap[$key]['created_at']));
                }
                $userRoomMap[$key]['nowType'] = 0;
                $userRoomMap[$key]['created_at'] = '';
            }
            $userRoomMap[$key]['list'][] = $val;
        }
        $microNumAll = count($userIds);
        //     有效上麦人数（含主播）
        //         每日上麦≥5分钟的人数
        $microNumTrue = 0;
        foreach ($userRoomMap as $val) {
            if (!empty($userRoomMap[$key]['created_at'])) {
                $userRoomMap[$key]['total'] = $userRoomMap[$key]['total'] + 60;
            }
            if ($userRoomMap[$key]['total'] >= 300) {
                $microNumTrue++;
            }
        }

        //用户总充值金额(合计）
        $rechargeAll = DB::table($this->rechargeOrderTable)
            ->where('pay_timestamp', '>=', $timeStr)
            ->where('pay_timestamp', '<=', $timeEnd)
            ->where('status', 1)
            ->sum('price');

        //充值总人数（合计）
        $userIds = DB::table($this->rechargeOrderTable)
            ->where('pay_timestamp', '>=', $timeStr)
            ->where('pay_timestamp', '<=', $timeEnd)
            ->where('status', 1)
            ->select('user_id')
            ->distinct()
            ->get();
        $userIds = self::objToArray($userIds);
        $userIds = array_column($userIds, 'user_id');
        $rechargeUserNum = count($userIds);

        // 用户充值人数（ios)
        $rechargeUserNumIos = 0;
        // 用户充值金额（IOS)
        $rechargeUserTotalIos = 0;
        // 用户充值人数（安卓)
        $rechargeUserNumAndroid = 0;
        // 用户充值金额（安卓)
        $rechargeUserTotalAndroid = 0;
        if (!empty($userIds)) {
            $loginLog = DB::table($this->userLoginLogTable)
                ->select('user_id', DB::raw('MIN(id) as id'))
                ->whereIn('user_id', $userIds)
                ->groupBy('user_id')
                ->get();
            $loginLog = self::objToArray($loginLog);
            if (!empty($loginLog)) {
                $ids = array_column($loginLog, 'id');
                $userAndroid = DB::table($this->userLoginLogTable)
                    ->whereIn('id', $ids)
                    ->where('os_name', 'Android')
                    ->select('user_id')
                    ->distinct()
                    ->get();
                $userAndroid = self::objToArray($userAndroid);
                $rechargeUserNumAndroid = count($userAndroid);

                if (!empty($userAndroid)) {
                    $rechargeUserTotalAndroid = DB::table($this->rechargeOrderTable)
                        ->where('pay_timestamp', '>=', $timeStr)
                        ->where('pay_timestamp', '<=', $timeEnd)
                        ->where('status', 1)
                        ->whereIn('user_id', array_column($userAndroid, 'user_id'))
                        ->sum('price');
                }

            }
            $rechargeUserNumIos = $rechargeUserNum - $rechargeUserNumAndroid;
            $rechargeUserTotalIos = $rechargeAll - $rechargeUserTotalAndroid;
        }

        // 首充人数（合计）
        // 每日完成首次充值的人数
        $firstChargeNum = 0;
        // 首充金额（合计）
        // 每日首次的总金额
        $firstChargeTotal = 0;
        if (!empty($userIds)) {
            $oldUserIds = DB::table($this->rechargeOrderTable)
                ->where('pay_timestamp', '<', $timeStr)
                ->where('status', 1)
                ->whereIn('user_id', $userIds)
                ->select('user_id')
                ->distinct()
                ->get();
            $oldUserIds = self::objToArray($oldUserIds);
            $oldUserIds = array_column($oldUserIds, 'user_id');
            $firstChargeUser = [];
            foreach ($userIds as $userId) {
                if (!in_array($userId, $oldUserIds)) {
                    $firstChargeUser[] = $userId;
                }
            }
            $firstChargeNum = count($firstChargeUser);

            if (!empty($firstChargeUser)) {
                $firstChargeTotal = DB::table($this->rechargeOrderTable)
                    ->where('pay_timestamp', '>=', $timeStr)
                    ->where('pay_timestamp', '<=', $timeEnd)
                    ->where('status', 1)
                    ->whereIn('user_id', $firstChargeUser)
                    ->sum('price');
            }

        }

        // 用户总消费金额(合计）
        $useDiamondAll = DB::table($this->diamondStreamTable)
            ->where('change_timestamp', '>=', $timeStr)
            ->where('change_timestamp', '<=', $timeEnd)
            ->where('diamond_value', '<', 0)
            ->sum('diamond_value');
        $useDiamondAll = abs($useDiamondAll);

        //消费总人数（合计）
        $userIds = DB::table($this->diamondStreamTable)
            ->where('change_timestamp', '>=', $timeStr)
            ->where('change_timestamp', '<=', $timeEnd)
            ->where('diamond_value', '<', 0)
            ->select('user_id')
            ->distinct()
            ->get();
        $userIds = self::objToArray($userIds);
        $userIds = array_column($userIds, 'user_id');
        $useDiamondUserNum = count($userIds);

        // 用户消费人数（ios)
        $useDiamondNumIos = 0;
        // 用户消费金额（IOS)
        $useDiamondTotalIos = 0;
        // 用户消费人数（安卓)
        $useDiamondNumAndroid = 0;
        // 用户消费金额（安卓)
        $useDiamondTotalAndroid = 0;
        if (!empty($userIds)) {
            $loginLog = DB::table($this->userLoginLogTable)
                ->select('user_id', DB::raw('MIN(id) as id'))
                ->whereIn('user_id', $userIds)
                ->groupBy('user_id')
                ->get();
            $loginLog = self::objToArray($loginLog);
            if (!empty($loginLog)) {
                $ids = array_column($loginLog, 'id');
                $userAndroid = DB::table($this->userLoginLogTable)
                    ->whereIn('id', $ids)
                    ->where('os_name', 'Android')
                    ->select('user_id')
                    ->distinct()
                    ->get();
                $userAndroid = self::objToArray($userAndroid);
                $useDiamondNumAndroid = count($userAndroid);

                if (!empty($userAndroid)) {
                    $useDiamondTotalAndroid = DB::table($this->diamondStreamTable)
                        ->where('change_timestamp', '>=', $timeStr)
                        ->where('change_timestamp', '<=', $timeEnd)
                        ->where('diamond_value', '<', 0)
                        ->whereIn('user_id', array_column($userAndroid, 'user_id'))
                        ->sum('diamond_value');
                    $useDiamondTotalAndroid = abs($useDiamondTotalAndroid);
                }
            }
            $useDiamondNumIos = $useDiamondUserNum - $useDiamondNumAndroid;
            $useDiamondTotalIos = $useDiamondAll - $useDiamondTotalAndroid;
        }

        $data = [
            'created_date' => date("Y-m-d", $timeStr),
            'type' => 1,
            'userNewNum' => $userNewNum,
            'activeNumAll' => $activeNumAll,
            'activeNumAndroid' => $activeNumAndroid,
            'activeNumIos' => $activeNumIos,
            'roomOpenNumAll' => $roomOpenNumAll,
            'roomOpenNumTrue' => $roomOpenNumTrue,
            'microNumAll' => $microNumAll,
            'microNumTrue' => $microNumTrue,
            'rechargeAll' => $rechargeAll,
            'rechargeUserNum' => $rechargeUserNum,
            'rechargeUserNumIos' => $rechargeUserNumIos,
            'rechargeUserTotalIos' => $rechargeUserTotalIos,
            'rechargeUserNumAndroid' => $rechargeUserNumAndroid,
            'rechargeUserTotalAndroid' => $rechargeUserTotalAndroid,
            'firstChargeNum' => $firstChargeNum,
            'firstChargeTotal' => $firstChargeTotal,
            'useDiamondAll' => $useDiamondAll,
            'useDiamondUserNum' => $useDiamondUserNum,
            'useDiamondNumIos' => $useDiamondNumIos,
            'useDiamondTotalIos' => $useDiamondTotalIos,
            'useDiamondNumAndroid' => $useDiamondNumAndroid,
            'useDiamondTotalAndroid' => $useDiamondTotalAndroid,
        ];

        $log = DB::connection($this->statCon)->table($this->statDailyTable)
            ->where('created_date', date("Y-m-d", $timeStr))
            ->where('type', 1)
            ->first();
        if (empty($log)) {
            $id = DB::connection($this->statCon)->table($this->statDailyTable)->insertGetId($data);
            if (empty($id)) {
                write_log("error_dailyStatistics", "stat_daily 新增失败", $data);
            }
        } else {
             unset($data['activeNumAll'],$data['activeNumAndroid'],$data['activeNumIos']);
             $id = DB::connection($this->statCon)->table($this->statDailyTable)
                 ->where('id', $log->id)->update($data);

            write_log("error_dailyStatistics", "stat_daily 数据已存在", $data);
        }
    }

    /**
     * 统计数据 每日数据
     * 更改流水逻辑
     * @author  
     * */
    public function statisticalDayRoom($timeStr, $timeEnd)
    {
        $dateStr = date("Y-m-d H:i:s", $timeStr);
        $dateEnd = date("Y-m-d H:i:s", $timeEnd);

        //查询对应送礼流水记录
        $alldata = DB::table('finance_union_room_stream')
            ->whereIn('data_type', [1, 2])
            ->where('created_at', '>=', $dateStr)
            ->where('created_at', '<=', $dateEnd)
            ->count();
        //计算页数
        $nums = 500;//一次多少条
        $page = ceil($alldata / $nums);

        //DB::connection($this->statCon)->table('new_daily_room')->truncate();
        for ($i = 0; $i < $page; $i++) {
            //偏移量
            $limitset = (($i + 1) - 1) * $nums;
            $GiftLog = DB::table('finance_union_room_stream')
                ->whereIn('data_type', [1, 2])
                ->where('created_at', '>=', $dateStr)
                ->where('created_at', '<=', $dateEnd)
                ->offset($limitset)->limit($nums)->get();
            $GiftLog = $this->objToArray($GiftLog);
            write_log("error_dailyStatistics", "$GiftLog", $page);
            $doneuserid = [];
            //处理流水表数据
            DB::beginTransaction();
            foreach ($GiftLog as $k => $v) {

                try {
                    $date = date('Y-m-d', strtotime($v['created_at']));
                    $check = DB::connection($this->statCon)->table('new_daily_room')->where(['created_date' => $date, 'roomId' => $v['room_id']])->first();
                    //查询房间流水数据统计用户总数
                    $userIds = DB::table('finance_union_room_stream')
                        ->where('room_id', $v['room_id'])
                        ->where('created_at', '>=', $dateStr)
                        ->where('created_at', '<=', $dateEnd)
                        ->select(['from_user_id'])
                        ->distinct()
                        ->get();
                    $userIds = self::objToArray($userIds);
                    $userIds = array_column($userIds, 'from_user_id');
                    $rechargeUserNum = count($userIds);
                    //查询数据中用户来源
                    $registerFrom = DB::table($this->userRegisterTable)->whereIn('user_id', $userIds)
                        ->where('os_name', 'Android')
                        ->select('user_id')
                        ->distinct()
                        ->get();
                    $userAndroid = self::objToArray($registerFrom);
                    $useDiamondNumAndroid = count($userAndroid);
                    if (!empty($check)) {
                        //检查用户注册来源
                        $registerFrom = DB::table($this->userRegisterTable)->where('user_id', $v['from_user_id'])->orderBy('time', 'ASC')->first();
                        $registerFrom = self::objToArray($registerFrom);
                        $allnum = $v['data_value'] * $v['data_num'];
                        DB::connection($this->statCon)->table('new_daily_room')->where('id', $check->id)->increment('useDiamondAll', $allnum);
                        if ($registerFrom['os_name'] == 'iPhone') {
                            DB::connection($this->statCon)->table('new_daily_room')
                                ->where('id', $check->id)
                                ->increment('useDiamondTotalIos', $allnum);
                        } else {
                            DB::connection($this->statCon)->table('new_daily_room')
                                ->where('id', $check->id)
                                ->increment('useDiamondTotalAndroid', $allnum);
                        }
                    } else {
                        $registerFrom = DB::table($this->userRegisterTable)->where('user_id', $v['from_user_id'])->orderBy('time', 'ASC')->first();
                        $registerFrom = self::objToArray($registerFrom);
                        $allnum = $v['data_value'] * $v['data_num'];
                        $insertdata['created_date'] = $date;
                        $insertdata['roomId'] = $v['room_id'];
                        $insertdata['useDiamondAll'] = $allnum;
                        $insertdata['useDiamondUserNum'] = $rechargeUserNum;

                        $insertdata['useDiamondNumIos'] = $rechargeUserNum-$useDiamondNumAndroid;
                        if ($registerFrom['os_name'] == 'iPhone') {
                            $insertdata['useDiamondTotalIos'] = $allnum;
                        }else{
                            $insertdata['useDiamondTotalAndroid'] = $allnum;
                        }
                        $insertdata['useDiamondNumAndroid'] = $useDiamondNumAndroid;

                        $insertdata['unionId'] = $v['union_id'];
                        $insertdata['roomActiveUserNum'] = 0;
                        write_log("error_dailyStatistics", "new_daily_room", $insertdata);
                        DB::connection($this->statCon)->table('new_daily_room')->insert($insertdata);
                    }
                    array_push($doneuserid, $v['from_user_id']);
                } catch (\Exception $e) {
                    DB::rollback();//事务回滚
                    write_log("error_dailyStatistics", "new_daily_room 新增失败", $v['id']);
                }
                DB::commit();
                //echo 'finance_union_room_stream中id为-' . $v['id'] . '-同步到每日流水表成功!' . PHP_EOL;
                unset($v);
            }
            unset($GiftLog);
            unset($insertdata);
        }
        write_log("dailyStatistics", "new_daily_room",'完成');
    }

}
